from app.db import db  # 从独立的 db 模块导入
from app.Models.FinanceModels.Income import Income  # 导入Income模型
from app.Models.FinanceModels.IncomeFirstCate import IncomeFirstCate
from app.Models.FinanceModels.IncomeSecondCate import IncomeSecondCate
from datetime import date
import pandas as pd


class IncomeDAO:
    """收入模型的数据访问对象"""

    @staticmethod
    def create_income(user_id, first_cate_id, second_cate_id, amount, date, remark=None):
        """
        创建新的收入记录
        :param user_id: 用户ID
        :param first_cate_id: 一级分类ID
        :param second_cate_id: 二级分类ID
        :param amount: 收入金额
        :param date: 收入日期（date类型）
        :param remark: 备注（可选）
        :return: 创建的收入记录对象
        """
        new_income = Income(
            user_id=user_id,
            first_cate_id=first_cate_id,
            second_cate_id=second_cate_id,
            amount=amount,
            date=date,
            remark=remark
        )
        db.session.add(new_income)
        db.session.commit()
        return new_income

    @staticmethod
    def get_income_by_id(income_id):
        """
        根据ID查询收入记录
        :param income_id: 收入记录ID
        :return: 收入记录对象或None
        """
        return Income.query.get(income_id)

    @staticmethod
    def get_incomes_by_user(user_id, start_date=None, end_date=None):
        """
        查询指定用户的收入记录（包含一级、二级分类名称），可按日期范围过滤
        :param user_id: 用户ID
        :param start_date: 开始日期（可选）
        :param end_date: 结束日期（可选）
        :return: 包含分类名称的收入记录列表（字典形式）
        """
        # 关联查询 Income、一级分类表、二级分类表，获取两级分类名称
        query = (db.session.query(
            Income,
            IncomeFirstCate.first_cate_name.label('first_cate_name'),  # 一级分类名称
            IncomeSecondCate.second_cate_name.label('second_cate_name')  # 二级分类名称
        ).join(
            IncomeFirstCate,
            Income.first_cate_id == IncomeFirstCate.id  # 关联一级分类
        ).join(
            IncomeSecondCate,
            Income.second_cate_id == IncomeSecondCate.id  # 关联二级分类
        ).filter(
            Income.user_id == user_id
        ))

        # 日期范围过滤
        if start_date:
            query = query.filter(Income.date >= start_date)
        if end_date:
            query = query.filter(Income.date <= end_date)

        # 按日期倒序排列（最新的在前）
        results = query.order_by(Income.date.desc()).all()

        # 整合结果：合并收入记录与两级分类名称
        income_list = []
        for income, first_cate_name, second_cate_name in results:
            # 将 Income 对象转换为字典（假设模型有 to_dict() 方法）
            income_dict = income.to_dict()
            # 添加一级分类名称
            income_dict['first_cate_name'] = first_cate_name
            # 添加二级分类名称
            income_dict['second_cate_name'] = second_cate_name
            income_list.append(income_dict)

        return income_list

    @staticmethod
    def get_incomes_by_category(first_cate_id=None, second_cate_id=None):
        """
        按分类查询收入记录
        :param first_cate_id: 一级分类ID（可选）
        :param second_cate_id: 二级分类ID（可选）
        :return: 收入记录列表
        """
        query = Income.query

        if first_cate_id:
            query = query.filter_by(first_cate_id=first_cate_id)
        if second_cate_id:
            query = query.filter_by(second_cate_id=second_cate_id)

        return query.order_by(Income.date.desc()).all()

    @staticmethod
    def update_income(income_id, **kwargs):
        """
        更新收入记录
        :param income_id: 收入记录ID
        :param kwargs: 要更新的字段（如amount, date, remark等）
        :return: 更新后的收入记录对象或None
        """
        income = IncomeDAO.get_income_by_id(income_id)
        if not income:
            return None

        # 批量更新字段
        for key, value in kwargs.items():
            if hasattr(income, key):
                setattr(income, key, value)

        db.session.commit()
        return income

    @staticmethod
    def delete_income(income_id):
        """
        删除收入记录
        :param income_id: 收入记录ID
        :return: 成功返回True，失败返回False
        """
        income = IncomeDAO.get_income_by_id(income_id)
        if not income:
            return False

        db.session.delete(income)
        db.session.commit()
        return True

    @staticmethod
    def get_income_summary(user_id, year, month=None):
        """
        获取用户的收入汇总（按年或按月）
        :param user_id: 用户ID
        :param year: 年份
        :param month: 月份（可选，不填则统计全年）
        :return: 汇总金额
        """
        query = Income.query.filter_by(user_id=user_id)

        # 过滤年份
        query = query.filter(db.extract('year', Income.date) == year)

        # 过滤月份（如果指定）
        if month:
            query = query.filter(db.extract('month', Income.date) == month)

        # 计算总和
        from sqlalchemy import func
        result = query.with_entities(func.sum(Income.amount)).first()
        return result[0] or 0.0  # 若没有数据则返回0.0

    @staticmethod
    def get_second_cates_by_first_cate(first_cate_id, user_id=None):
        """
        根据一级分类ID查询关联的二级分类信息（去重）
        :param first_cate_id: 一级分类ID
        :param user_id: 用户ID（可选，用于筛选特定用户的记录）
        :return: 二级分类列表（如[2, 3, 5]）
        """
        query = IncomeSecondCate.query.filter_by(first_cate_id=first_cate_id)

        # 查询去重的二级分类ID并排序
        second_cates = query.distinct(IncomeSecondCate.id).order_by(IncomeSecondCate.id).all()
        print(second_cates)

        # 提取元组中的ID，返回列表
        return [item.to_dict() for item in second_cates]

    @staticmethod
    def get_all_first_cates():
        """
        获取所有一级分类
        :return:
        """
        categories = IncomeFirstCate.query.all()
        # 利用模型自带的to_dict()方法转换为字典列表
        cate_data = [cate.to_dict() for cate in categories]
        return cate_data

